﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Windows.Forms;
using System.Windows.Forms.Calendar;
using System.Drawing;

namespace Helix_Network_Supervisor_3
{
    class Schedule
    {
        #region Fields

        private ApplicationSettings appSettings = new ApplicationSettings();
        private int[] scheduleItemCount = new int[7];
        string saveScheduleFilePath = "";
        string currentScheduleFileName = "New Schedule";
        FileManipulator fm = new FileManipulator();
        ImageList calendarItemImageList;

        #endregion Fields

        #region Ctor

        public Schedule(ImageList imageList)
        {
            calendarItemImageList = imageList;
        }

        #endregion Ctor

        #region Properties

        public string CurrentScheduleFileName
        {
            get { return currentScheduleFileName; }
        }

        #endregion Properties

        #region Public Methods

        /// <summary>
        /// Populate the Schedule List View with the Currently Saved Schedules
        /// </summary>
        /// <param name="scheduleListView"></param>
        public void PopulateScheduleListView(ListView scheduleListView)
        {
            scheduleListView.Clear();

            scheduleListView.Columns.Add("File Name (Double Click to Open)", 200, HorizontalAlignment.Left);
            scheduleListView.Columns.Add("File Path", 1, HorizontalAlignment.Left);

            //string schedulePath = @"C:\Users\Greg\Documents\Helix\Schedules";
            string schedulePath = appSettings.scheduleFilePath;

            try
            {
                DirectoryInfo di = new DirectoryInfo(schedulePath);
                FileInfo[] arrFiles = di.GetFiles();

                string[] listItems = new string[2];
                string fileName = "";
                foreach (FileInfo tempFile in arrFiles)
                {
                    fileName = tempFile.Name;
                    fileName.ToUpper();
                    if (!fileName.Equals("PAGEFILE.SYS"))
                    {
                        int iImage = 1;
                        string fileExtension = tempFile.Extension;

                        listItems[0] = fileName;
                        listItems[1] = schedulePath;

                        ListViewItem lviItem = new ListViewItem(listItems, iImage);

                        scheduleListView.Items.Add(lviItem);
                    }
                }
            }
            catch
            {
            }

        }

        /// <summary>
        /// Initialize the Schedule
        /// </summary>
        /// <param name="scheduleCalendar"></param>
        public void InitilizeScheduleControls(Calendar scheduleCalendar)
        {
            scheduleCalendar.SetViewRange(new DateTime(2010, 8, 1), new DateTime(2010, 8, 7));
            scheduleCalendar.Items.Clear();
            currentScheduleFileName = "New Schedule";
            scheduleCalendar.CalendarNeedsToBeSaved = false;

            for (int i = 0; i < 7; i++)
            {
                scheduleItemCount[i] = 0;
            }
        }

        /// <summary>
        /// Add an Item to the Schedule
        /// </summary>
        /// <param name="scheduleCalendar"></param>
        /// <param name="itemType"></param>
        /// <returns></returns>
        public bool AddScheduleItem(Calendar scheduleCalendar, string itemType)
        {
            DateTime startTime;
            DateTime endTime;

            if (scheduleCalendar.SelectedElementStart == null || scheduleCalendar.SelectedElementEnd == null)
            {
                startTime = new DateTime(2010, 8, 1, 17, 00, 00);
                endTime = new DateTime(2010, 8, 1, 22, 00, 00);
            }
            else
            {
                startTime = scheduleCalendar.SelectedElementStart.Date;              
                TimeSpan timeScaleUnit = new TimeSpan(0, (int)scheduleCalendar.TimeScale, 0);
                endTime = scheduleCalendar.SelectedElementEnd.Date.Add(timeScaleUnit);
                
            }

            if (endTime < startTime)
            {
                DateTime dt = endTime;
                endTime = startTime;
                startTime = dt;
            }

            ScheduleItemForm scheduleItemForm = new ScheduleItemForm(itemType, startTime, endTime);
            string itemPath = "";
            string columnTitle = "";
            Color itemColor;
            int imageIndex;

            switch (itemType)
            {
                case "Show":
                    itemPath = appSettings.showFilePath;
                    columnTitle = "Select Show";
                    itemColor = Color.SteelBlue;
                    imageIndex = 0;
                    break;

                case "Playlist":
                    itemPath = appSettings.playlistFilePath;
                    columnTitle = "Select Playlist";
                    itemColor = Color.Goldenrod;
                    imageIndex = 1;
                    break;

                case "Trigger":
                    itemPath = appSettings.showFilePath;
                    columnTitle = "Select Show to Trigger";
                    itemColor = Color.MediumSpringGreen;
                    imageIndex = 2;
                    break;

                default:
                    return false;
            }

            scheduleItemForm.populateItemList(itemPath, columnTitle);

            bool itemInserted = false;

            if (scheduleItemForm.ShowDialog() == DialogResult.OK)
            {
                List<int> dayList = scheduleItemForm.DayList;
                string showName = scheduleItemForm.ItemName;
                string showPath = scheduleItemForm.ItemPath;

                string[] dayOfWeek = new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

                if (dayList.Count < 1)
                {
                    MessageBox.Show("The Day of the Week was not selected.  Please try again.", "Helix Scheduler - Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    return false;
                }

                if (showName == "")
                {
                    if (itemType == "Show")
                    {
                        MessageBox.Show("The Show Name was not selected.  Please try again.", "Helix Scheduler - Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    }
                    else if (itemType == "Playlist")
                    {
                        MessageBox.Show("The Playlist Name was not selected.  Please try again.", "Helix Scheduler - Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Stop);

                    }
                    else
                    {
                        MessageBox.Show("The Show to be triggered was not selected.  Please try again.", "Helix Scheduler - Error",
                            MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    }
                    return false;
                }

                foreach (int dayOfWeekIndex in dayList)
                {
                    // Check to make sure there isn't already 9 elements in the day
                    if (scheduleItemCount[dayOfWeekIndex] == 9)
                    {
                        MessageBox.Show("There can be no more than 9 shows, playlists and triggers in any day.\r" +
                        "This entry for " + dayOfWeek[dayOfWeekIndex] + 
                        " would exceed that amount.\rPlease delete one of the existing items or select a different day.",
                        "Helix Scheduler - Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);

                        return false;
                    }

                    CalendarItem calendarItem = new CalendarItem(scheduleCalendar);
                    DateTime actualStartTime = new DateTime(2010, 8, dayOfWeekIndex + 1, 
                        scheduleItemForm.StartTime.Hour, scheduleItemForm.StartTime.Minute, scheduleItemForm.StartTime.Second);

                    DateTime actualEndTime = new DateTime(2010, 8, dayOfWeekIndex + 1, 
                        scheduleItemForm.EndTime.Hour, scheduleItemForm.EndTime.Minute, scheduleItemForm.EndTime.Second);

                    calendarItem.StartDate = actualStartTime;
                    calendarItem.EndDate = actualEndTime;
                    calendarItem.Text = scheduleItemForm.ItemName;
                    calendarItem.ItemPath = scheduleItemForm.ItemPath;
                    calendarItem.ItemType = itemType;
                    calendarItem.ApplyColor(itemColor);
                    calendarItem.ForeColor = Color.Black;
                    calendarItem.Image = calendarItemImageList.Images[imageIndex];
                    calendarItem.ImageAlign = CalendarItemImageAlign.North;

                    scheduleCalendar.SelectedElementStart = null;
                    scheduleCalendar.SelectedElementEnd = null;

                    itemInserted = (scheduleCalendar.AddCalendarItem(calendarItem));

                    scheduleItemCount[dayOfWeekIndex]++;                  
                }
            }

            return itemInserted;
        }

        /// <summary>
        /// Edit the selected Schedule Item
        /// </summary>
        /// <param name="scheduleCalendar"></param>
        /// <returns></returns>
        public bool EditScheduleItem(Calendar scheduleCalendar)
        {
            try
            {
                CalendarItemCollection scheduleItems = scheduleCalendar.Items;

                foreach (CalendarItem scheduleItem in scheduleItems)
                {
                    if (scheduleItem.Selected == true)
                    {
                        DateTime startTime = scheduleItem.StartDate;
                        DateTime endTime = scheduleItem.EndDate;
                        string itemType = scheduleItem.ItemType;
                        string formTitle = "Edit " + itemType;
                        ScheduleItemForm scheduleItemForm = new ScheduleItemForm(itemType, formTitle, startTime, endTime);
                        string itemPath = "";
                        string columnTitle = "";
                        Color itemColor;

                        switch (itemType)
                        {
                            case "Show":
                                {
                                    itemPath = appSettings.showFilePath;
                                    columnTitle = "Select Show";
                                    itemColor = Color.SteelBlue;
                                }
                                break;

                            case "Playlist":
                                {
                                    itemPath = appSettings.playlistFilePath;
                                    columnTitle = "Select Playlist";
                                    itemColor = Color.Goldenrod;
                                }
                                break;

                            case "Trigger":
                                {
                                    itemPath = appSettings.showFilePath;
                                    columnTitle = "Select Show to Trigger";
                                    itemColor = Color.MediumSpringGreen;
                                }
                                break;

                            default:
                                {
                                    return false;
                                }
                        }

                        string initialSelectedItem = scheduleItem.Text;

                        scheduleItemForm.populateItemList(itemPath, columnTitle, initialSelectedItem);

                        if (scheduleItemForm.ShowDialog() == DialogResult.OK)
                        {
                            List<int> dayList = scheduleItemForm.DayList;
                            string showName = scheduleItemForm.ItemName;
                            string showPath = scheduleItemForm.ItemPath;

                            string[] dayOfWeek = new string[] { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" };

                            if (dayList.Count < 1)
                            {
                                MessageBox.Show("The Day of the Week was not selected.  Please try again.", "Helix Scheduler - Error",
                                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
                                return false;
                            }

                            if (showName == "")
                            {
                                if (itemType == "Show")
                                {
                                    MessageBox.Show("The Show Name was not selected.  Please try again.", "Helix Scheduler - Error",
                                        MessageBoxButtons.OK, MessageBoxIcon.Stop);
                                }
                                else if (itemType == "Playlist")
                                {
                                    MessageBox.Show("The Playlist Name was not selected.  Please try again.", "Helix Scheduler - Error",
                                        MessageBoxButtons.OK, MessageBoxIcon.Stop);

                                }
                                else
                                {
                                    MessageBox.Show("The Show to be triggered was not selected.  Please try again.", "Helix Scheduler - Error",
                                        MessageBoxButtons.OK, MessageBoxIcon.Stop);
                                }
                                return false;
                            }

                            foreach (int dayOfWeekIndex in dayList)
                            {
                                // Check to make sure there isn't already 9 elements in the day
                                if (scheduleItemCount[dayOfWeekIndex] == 9)
                                {
                                    MessageBox.Show("There can be no more than 9 shows, playlists and triggers in any day.\r" +
                                    "This entry for " + dayOfWeek[dayOfWeekIndex] +
                                    " would exceed that amount.\rPlease delete one of the existing items or select a different day.",
                                    "Helix Scheduler - Error", MessageBoxButtons.OK, MessageBoxIcon.Stop);

                                    return false;
                                }

                                CalendarItem calendarItem = new CalendarItem(scheduleCalendar);
                                DateTime actualStartTime = new DateTime(2010, 8, dayOfWeekIndex + 1,
                                    scheduleItemForm.StartTime.Hour, scheduleItemForm.StartTime.Minute, scheduleItemForm.StartTime.Second);

                                DateTime actualEndTime = new DateTime(2010, 8, dayOfWeekIndex + 1,
                                    scheduleItemForm.EndTime.Hour, scheduleItemForm.EndTime.Minute, scheduleItemForm.EndTime.Second);

                                calendarItem.StartDate = actualStartTime;
                                calendarItem.EndDate = actualEndTime;
                                calendarItem.Text = scheduleItemForm.ItemName;
                                calendarItem.ItemPath = scheduleItemForm.ItemPath;
                                calendarItem.ItemType = itemType;
                                calendarItem.ApplyColor(itemColor);
                                calendarItem.ForeColor = Color.Black;
                                calendarItem.Image = scheduleItem.Image;
                                calendarItem.ImageAlign = CalendarItemImageAlign.North;

                                scheduleCalendar.SelectedElementStart = null;
                                scheduleCalendar.SelectedElementEnd = null;

                                if (scheduleCalendar.AddCalendarItem(calendarItem))
                                {
                                    scheduleItems.Remove(scheduleItem);
                                }
                            }
                            //return true;

                        }
                    }
                }
                return false;
            }
                    
            catch
            {
                return false;
            }
        }

        /// <summary>
        /// Delete the selected Items from the Schedule
        /// </summary>
        /// <param name="scheduleCalendar"></param>
        /// <returns></returns>
        public bool DeleteScheduleItems(Calendar scheduleCalendar)
        {
            bool itemsDeleted = false;
            CalendarItemCollection scheduleItems = scheduleCalendar.Items;

            Stack<CalendarItem> toDelete = new Stack<CalendarItem>();

            foreach (CalendarItem item in scheduleItems)
            {
                if (item.Selected)
                {
                    toDelete.Push(item);
                }
            }

            if (toDelete.Count > 0)
            {
                while (toDelete.Count > 0)
                {
                    CalendarItem item = toDelete.Pop();

                    int dayIndex = item.StartDate.Day - 1;

                    scheduleItemCount[dayIndex]--;

                    scheduleItems.Remove(item);
                }

                itemsDeleted = true;
            }

            if (scheduleItems.Count > 0)
            {
                scheduleCalendar.CalendarNeedsToBeSaved = true;
            }
            else
            {
                scheduleCalendar.CalendarNeedsToBeSaved = false;
            }
            return itemsDeleted;
        }

        /// <summary>
        /// Open the currently selected Schedule
        /// </summary>
        /// <param name="scheduleCalendar"></param>
        /// <param name="schedulePath"></param>
        /// <returns></returns>
        public bool OpenSchedule(Calendar scheduleCalendar, string schedulePath)
        {
            if (scheduleCalendar.CalendarNeedsToBeSaved == true)
            {
                DialogResult dR = MessageBox.Show("The current schedule has not been saved.  Save the current schedule?",
                    "Helix Schedule Warning", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                if (dR == DialogResult.Yes)
                {
                    //saveSchedule();
                }
                else if (dR == DialogResult.Cancel)
                {
                    return false;
                }
            }

            InitilizeScheduleControls(scheduleCalendar);
            saveScheduleFilePath = schedulePath;

            ListView.ListViewItemCollection lvicToOpen = fm.OpenScheduleFile(schedulePath);

            if (lvicToOpen.Count == 0)
            {
                saveScheduleFilePath = "";
                return false;
            }

            foreach (ListViewItem lvi in lvicToOpen)
            {
                /*
                 *Open a Schedule file from an XML file.
                 *The Schedule data is in a ListViewItemCollection with the following order:
                 *Item[0]=Day Index (1=Sunday...7=Saturday)
                 *Item[1]=Day
                 *Item[2]=Start Time (24hr format)
                 *Item[3]=End Time (24hr format)
                 *Item[4]=Show Name
                 *Item[5]=Show Path
                 *Item[6]=Type ("S"=Show, "P"=Playlist)
                */

                string itemText = lvi.SubItems[4].Text;
                string itemPath = lvi.SubItems[5].Text;
                string itemType = lvi.SubItems[6].Text;
                string formatedStartTime = lvi.SubItems[2].Text;
                string formatedEndTime = lvi.SubItems[3].Text;
                string dayIndex = lvi.SubItems[0].Text;
                int day = int.Parse(dayIndex);
                DateTime startTime;
                DateTime endTime;
                try
                {
                    startTime = DateTime.Parse(formatedStartTime);
                }
                catch
                {
                    //Formated StartTime is probably in old format so need to convert
                    string formatedHour = formatedStartTime.Substring(0, 2);
                    string formatedMin = formatedStartTime.Substring(2, 2);
                    int hour = int.Parse(formatedHour);
                    int min = int.Parse(formatedMin);

                    startTime = new DateTime(2010, 8, day, hour, min, 0);
                }

                try
                {
                    endTime = DateTime.Parse(formatedEndTime);
                }
                catch
                {
                    //Formated StartTime is probably in old format so need to convert
                    string formatedHour = formatedEndTime.Substring(0, 2);
                    string formatedMin = formatedEndTime.Substring(2, 2);
                    int hour = int.Parse(formatedHour);
                    int min = int.Parse(formatedMin);

                    endTime = new DateTime(2010, 8, day, hour, min, 0);
                }

                if (itemType == "S")
                {
                    itemType = "Show";
                }

                if (itemType == "P")
                {
                    itemType = "Playlist";
                }

                Color itemColor;
                int imageIndex = 0;
                switch (itemType)
                {
                    case "Show":
                        itemColor = Color.SteelBlue;
                        imageIndex = 0;
                        break;

                    case "Playlist":
                        itemColor = Color.Goldenrod;
                        imageIndex = 1;
                        break;

                    case "Trigger":
                        itemColor = Color.MediumSpringGreen;
                        imageIndex = 2;
                        break;

                    default:
                        return false;
                }

                CalendarItem newItem = new CalendarItem(scheduleCalendar, startTime, endTime, itemText, itemType, itemPath);
                newItem.ApplyColor(itemColor);
                newItem.ForeColor = Color.Black;
                newItem.Image = calendarItemImageList.Images[imageIndex];
                newItem.ImageAlign = CalendarItemImageAlign.North;

                scheduleItemCount[day - 1]++;

                scheduleCalendar.AddCalendarItem(newItem);

            }

            scheduleCalendar.CalendarNeedsToBeSaved = false;
            currentScheduleFileName = Path.GetFileName(saveScheduleFilePath);
            return true;
        }

        /// <summary>
        /// Save the current Schedule
        /// </summary>
        /// <param name="scheduleCalendar"></param>
        /// <returns></returns>
        public bool SaveSchedule(Calendar scheduleCalendar)
        {
            if (saveScheduleFilePath == "")
            {
                SaveFileDialog saveFileDialog = new SaveFileDialog();

                saveFileDialog.DefaultExt = "sch";
                saveFileDialog.Filter = "Helix Schedule Files|*.sch";

                saveFileDialog.InitialDirectory = appSettings.scheduleFilePath;
                //Call the SaveFileDialog
                if (saveFileDialog.ShowDialog() == DialogResult.OK)
                {
                    saveScheduleFilePath = saveFileDialog.FileName;
                    string fileName = Path.GetFileName(saveScheduleFilePath);
                    saveScheduleFilePath = appSettings.scheduleFilePath + @"\" + fileName;
                }
                else
                {
                    return false;
                }
            }

            CalendarItemCollection scheduleItems = scheduleCalendar.Items;

            //Sort the items from earliest to latest
            CalendarItemComparer calendarItemComparer = new CalendarItemComparer();
            scheduleItems.Sort(calendarItemComparer);

            fm.SaveSchedule(scheduleItems, saveScheduleFilePath);
            scheduleCalendar.CalendarNeedsToBeSaved = false;
            currentScheduleFileName = Path.GetFileName(saveScheduleFilePath);
            return true;
        }

        /// <summary>
        /// Save the current Schedule with a new file name
        /// </summary>
        /// <param name="scheduleCalendar"></param>
        /// <returns></returns>
        public bool SaveAsSchedule(Calendar scheduleCalendar)
        {
            string originalFilePath = saveScheduleFilePath;
            saveScheduleFilePath = "";

            if (SaveSchedule(scheduleCalendar) == true)
            {
                return true;
            }
            else
            {
                saveScheduleFilePath = originalFilePath;
                return false;
            }
        }

        /// <summary>
        /// Create a new Schedule
        /// </summary>
        /// <param name="scheduleCalendar"></param>
        /// <returns></returns>
        public bool NewSchedule(Calendar scheduleCalendar)
        {
            if (scheduleCalendar.CalendarNeedsToBeSaved)
            {
                DialogResult dR = MessageBox.Show("The current schedule has not been saved.  Save the current schedule?",
                    "Helix Schedule Warning", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
                if (dR == DialogResult.Yes)
                {
                    SaveSchedule(scheduleCalendar);
                }
                else if (dR == DialogResult.Cancel)
                {
                    return false;
                }
            }
            InitilizeScheduleControls(scheduleCalendar);

            return true;
        }

        /// <summary>
        /// Get the number of Items in the specified day
        /// </summary>
        /// <param name="dayIndex"></param>
        /// <returns></returns>
        public int GetScheduleItemCount(int dayIndex)
        {
            if (dayIndex >= 0 && dayIndex < 7)
            {
                return scheduleItemCount[dayIndex];
            }
            else
            {
                return -1;
            }

        }

        public void UpdateScheduleItemCount(Calendar scheduleCalendar)
        {
            for (int index = 0; index < 7; index++)
            {
                scheduleItemCount[index] = 0;
            }

            CalendarItemCollection itemCollection = scheduleCalendar.Items;

            CalendarItemComparer calendarItemComparer = new CalendarItemComparer();

            itemCollection.Sort(calendarItemComparer);

            foreach (CalendarItem item in itemCollection)
            {
                int dayIndex = item.StartDate.Day - 1;
                scheduleItemCount[dayIndex]++;
            }
        }

        #endregion Public Methods

        #region Private Methods

        #endregion Private Methods
    }
}
